package org.tobaccomain.service.serviceImpl;


import ch.qos.logback.core.joran.action.ImcplicitActionDataForBasicProperty;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import dingsung.com.cn.Card;
import dingsung.com.cn.NetCardReader;
import dingsung.com.cn.ReaderState;
import jakarta.annotation.Resource;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.tobaccomain.mapper.DeskMapper;
import org.tobaccomain.mapper.TobaccoDetailMapper;
import org.tobaccomain.mapper.TobaccoMapper;
import org.tobaccomain.mapper.YearMapper;
import org.tobaccomain.pojo.dto.DownloadParam;
import org.tobaccomain.pojo.dto.PageTobacco;
import org.tobaccomain.pojo.dto.TobaccoInfo;
import org.tobaccomain.pojo.entity.*;
import org.tobaccomain.pojo.vo.PageResult;
import org.tobaccomain.service.TobaccoService;
import org.tobaccomain.utils.RfidUtils;

import java.io.*;
import java.net.URLEncoder;
import java.time.Year;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static org.apache.poi.ss.usermodel.CellType.STRING;

@Slf4j
@Service
public class TobaccoServiceImpl implements TobaccoService {

    @Resource
    private TobaccoMapper tobaccoMapper;
    @Resource
    private DeskMapper deskMapper;
    @Resource
    private YearMapper yearMapper;
    @Resource
    private TobaccoDetailMapper tobaccoDetailMapper;
    private String[] province ={"河北","山西","辽宁","吉林","黑龙江","江苏","浙江","安徽","福建","江西","山东","河南","湖北","湖南","广东","海南","四川","贵州","云南","陕西","甘肃","青海","台湾","内蒙古","广西","西藏","宁夏","新疆","北京","天津","上海","重庆","香港","澳门"};



    //添加单料烟基本信息
    @Override
    @Transactional
    public void addTobaccoBasic(TobaccoBasic tobaccoBasic){
        tobaccoMapper.insert(tobaccoBasic);
        //设置rfid不可使用
        deskMapper.setRfidUnavailable(tobaccoBasic.getRfid());
        //更新库存储量
        deskMapper.updateCategories(1);
        //更新产地信息
        LocationData locationData = new LocationData();
        locationData.setNumber(1);
        locationData.setLocation(tobaccoBasic.getLocation());
        deskMapper.updateLocationData(locationData);
        //更新年份数据
        Year year = tobaccoBasic.getYear();
        Integer number = yearMapper.selectNumber(year);
        YearData yearData = new YearData();
        yearData.setYear(year);
        yearData.setNumber(1);
        if (number == null){
            yearMapper.insert(yearData);
        }else {
            yearMapper.updateNumber(yearData);
        }
    }

    //删除单料烟信息
    @Override
    @Transactional
    public void delTobacco(TobaccoBasic tobaccoBasic) {
        Long id = tobaccoBasic.getId();
        //根据id删除单料烟基本信息
        tobaccoMapper.deleteById(id);
        //根据id删除单料烟详细信息
        tobaccoDetailMapper.deleteById(id);
        //回收rfid
        deskMapper.setRfidAvailable(tobaccoBasic.getRfid());
        //更新库存数量
        deskMapper.updateCategories(-1);
        //更新产地信息
        LocationData locationData = new LocationData();
        locationData.setNumber(-1);
        locationData.setLocation(tobaccoBasic.getLocation());
        deskMapper.updateLocationData(locationData);
        //更新年份数据
        Year year = tobaccoBasic.getYear();
        Integer count = yearMapper.selectNumber(year);
        if (count == 1){
            yearMapper.deleteYear(year);
        }else {
            YearData yearData = new YearData();
            yearData.setYear(tobaccoBasic.getYear());
            yearData.setNumber(-1);
            yearMapper.updateNumber(yearData);
        }
    }


    @Override
    public void modifyTobaccoInfo(TobaccoInfo tobaccoInfo) {

        UpdateWrapper<TobaccoBasic> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("info", tobaccoInfo.getInfo())
                .eq("id", tobaccoInfo.getId());
        tobaccoMapper.update(null, updateWrapper);
    }

    //修改单料烟基本信息
    @Override
    public void modifyTobacco(TobaccoBasic tobaccoBasic){
        //根据id查询的单料烟
        Long id = tobaccoBasic.getId();

        //判断location是否改变
        String location1 = tobaccoBasic.getLocation();
        TobaccoBasic tobaccoBasicInDB = tobaccoMapper.selectById(id);
        String location2 = tobaccoBasicInDB.getLocation();
        if (!location1.equals(location2)){
            LocationData locationData1 = new LocationData();
            locationData1.setLocation(location1);
            locationData1.setNumber(1);
            deskMapper.updateLocationData(locationData1);
            LocationData locationData2 = new LocationData();
            locationData2.setLocation(location2);
            locationData2.setNumber(-1);
            deskMapper.updateLocationData(locationData2);
        }
        //判断年份是否正常
        Year year1 = tobaccoBasic.getYear();
        Year year2 = tobaccoBasicInDB.getYear();
        if (!year1.equals(year2)){
            //判断年份数据是否存在
            Integer count = yearMapper.selectNumber(year1);
            log.info("year1 -- count = {}",count);
            YearData yearData1 = new YearData();
            yearData1.setYear(year1);
            yearData1.setNumber(1);
            if (count == null){
                yearMapper.insert(yearData1);
            }else {
                yearMapper.updateNumber(yearData1);
            }
            //判断yearData2的个数是不是为1
            count = yearMapper.selectNumber(year2);
            if (count == 1){
                yearMapper.deleteYear(year2);
            }else {
                YearData yearData2 = new YearData();
                yearData2.setYear(year2);
                yearData2.setNumber(-1);
                yearMapper.updateNumber(yearData2);
            }
        }
        tobaccoMapper.updateById(tobaccoBasic);
    }

    //单料烟分页查询
    @Override
    @Transactional
    public PageResult getTobaccoList(PageTobacco pageTobacco) {
        PageResult pageResult = new PageResult();
        //获取记录数
        List<TobaccoBasic> list = tobaccoMapper.selectTobaccoList(pageTobacco);
        //获取总记录数
        Integer total = tobaccoMapper.count(pageTobacco);
        pageResult.setRows(list);
        pageResult.setTotal(total);
        return pageResult;
    }
    //根据id获取单料烟的基本信息
    @Override
    public TobaccoBasic getTobaccoBasicInfoById(Integer id) {
        return tobaccoMapper.selectById(id);
    }

    //单料烟数据导出
    @Override
    public void downloadTobaccoData(DownloadParam param,HttpServletResponse response){
        List<TobaccoBasic> list;
        //根据ids判断导出哪些数据
        if (StringUtils.hasLength(param.getIds())) {
            //根据指定的id下载数据
            List<String> ids = List.of(param.getIds().split(","));
            log.info("这次需要下载的单料烟的信息为:{}", ids);
            //根据ids去查询需要下载的数据
            list = tobaccoMapper.downloadTobaccos(ids);
        } else {
            //根据查询条件获取所有数据
            log.info("根据查询条件获取所有数据{}", param);
            list = tobaccoMapper.downloadAllTobaccos(param);
        }
        downLoadData(response, list);
    }

    //单料烟详细数据导入
    @Override
    //添加事务保证数据一致性
    @Transactional
    public void uploadTobaccoDetail(MultipartFile file) throws IOException {
        XSSFWorkbook excel = new XSSFWorkbook(file.getInputStream());
        //读出数据
        XSSFSheet sheet = excel.getSheetAt(0);
        int rowNum = sheet.getLastRowNum();
        //定义列表保存单料烟详细数据
        List<TobaccoDetail> detailList =new ArrayList<>();
        //定义列表保存单料烟基本数据
        List<TobaccoBasic> basicList =new ArrayList<>();
        //定义列表存储rfid号
        List<Rfid> rfidList = new ArrayList<>();
        //定义列表存储年份信息
        List <Year> yearList = new ArrayList<>();
        //定义列表存储产地信息
        List <String> locationList = new ArrayList<>();
        //定义计数器统计产地在国外的单料烟个数
        int foreignCount = 0;
        for (int i = 1; i <=rowNum ; i++) {
            //创建一个单料烟基本对象
            TobaccoBasic tobaccoBasic = new TobaccoBasic();
            XSSFRow row = sheet.getRow(i);

            //获取rfid
            long rfidValue = (long) row.getCell(1).getNumericCellValue();
            tobaccoBasic.setRfid(rfidValue);
            //根据获取到的rfid值创建rfid对象
            Rfid rfid = new Rfid(rfidValue,0);
            rfidList.add(rfid);

            //获取物料号（id）
            long id = (long) row.getCell(2).getNumericCellValue();
            tobaccoBasic.setId(id);
            //获取批次信息
            String batch;
            if (row.getCell(3).getCellType() == STRING){
                batch = row.getCell(3).getStringCellValue();
            }else {
                batch = String.valueOf((int) row.getCell(3).getNumericCellValue());
            }
            //获取物料描述
            String description = "";
            if (row.getCell(4) != null){
                description = row.getCell(4).getStringCellValue();
                String[] split = description.split(";");
                //获取年份
                Year year = Year.parse(split[0]);
                tobaccoBasic.setYear(year);
                yearList.add(year);
                //获取产地
                String location = split[2];
                tobaccoBasic.setLocation(location);
                basicList.add(tobaccoBasic);
                //判断单料烟是否产自中国
                boolean flag = isChineseTobacco(location);
                if (flag){
                    locationList.add(location);
                }else {
                    foreignCount++;
                }
                //获取名称
                String name = split[5];
                tobaccoBasic.setName(name);
                //设置评价状态
                tobaccoBasic.setEvaluate(1);
                //TODO:设置单料烟部位
                tobaccoBasic.setPart("叶");
            }
            //获取等级类别
            int rank = 0;
            if (row.getCell(5) != null){
                rank = (int)row.getCell(5).getNumericCellValue();
            }
            //获取干草香
            double ganCaoFragrant = 0;
            if (row.getCell(6) != null){
               ganCaoFragrant = row.getCell(6).getNumericCellValue();
            }
            //获取清甜香
            double qingTianFragrant = 0;
            if (row.getCell(7) != null){
                qingTianFragrant = row.getCell(7).getNumericCellValue();
            }
            //获取正甜香
            double zhengTianFragrant = 0;
            if (row.getCell(8) != null){
                zhengTianFragrant = row.getCell(8).getNumericCellValue();
            }
            //获取焦甜香
            double jiaoTianFragrant = 0;
            if (row.getCell(9) != null){
                jiaoTianFragrant = row.getCell(9).getNumericCellValue();
            }
            //获取青香
            double qingFragrant = 0;
            if (row.getCell(10) != null){
                qingFragrant = row.getCell(10).getNumericCellValue();
            }
            //获取木香
            double muFragrant = 0;
            if (row.getCell(11) != null){
                muFragrant = row.getCell(11).getNumericCellValue();
            }
            //获取焦香
            double jiaoFragrant = 0;
            if (row.getCell(12) != null){
                jiaoFragrant = row.getCell(12).getNumericCellValue();
            }
            //获取辛香
            double xinFragrant = 0;
            if (row.getCell(13) != null){
                xinFragrant = row.getCell(13).getNumericCellValue();
            }
            //获取丰富度
            double richness = 0;
            if (row.getCell(14) != null){
                richness = row.getCell(14).getNumericCellValue();
            }

            //获取香气状态
            double fragranceState = 0;
            if (row.getCell(15) != null){
                fragranceState = row.getCell(15).getNumericCellValue();
            }
            //获取香型类型
            String fragranceType = "";
            if (row.getCell(16) != null){
                fragranceType = row.getCell(16).getStringCellValue();
            }
            //获取香型程度
            double fragranceDegree = 0;
            if (row.getCell(17) != null){
                fragranceDegree = row.getCell(17).getNumericCellValue();
            }
            //获取浓度
            double concentration = 0;
            if (row.getCell(18) != null){
                concentration = row.getCell(18).getNumericCellValue();
            }
            //获取劲头
            double energy = 0;
            if (row.getCell(19) != null){
                energy = row.getCell(19).getNumericCellValue();
            }
            //获取流畅
            double fluency = 0;
            if (row.getCell(20) != null){
                fluency = row.getCell(20).getNumericCellValue();
            }
            //获取绵长
            double mianChang = 0;
            if (row.getCell(21) != null){
                mianChang = row.getCell(21).getNumericCellValue();
            }
            //获取香气质
            double fragranceQuality = 0;
            if (row.getCell(22) != null){
                fragranceQuality = row.getCell(22).getNumericCellValue();
            }
            //获取香气量
            double fragranceQuantity = 0;
            if (row.getCell(23) != null){
                fragranceQuantity = row.getCell(23).getNumericCellValue();
            }
            //获取透发型
            double penetrability = 0;
            if (row.getCell(24) != null){
                penetrability = row.getCell(24).getNumericCellValue();
            }
            //获取杂气程度
            double zaQiDegree = 0;
            if (row.getCell(25) != null){
                zaQiDegree = row.getCell(25).getNumericCellValue();
            }
            //获取杂气种类
            String zaQiType = "";
            if (row.getCell(26) != null){
                zaQiType = row.getCell(26).getStringCellValue();
            }
            //获取细腻程度
            double exquisiteDegree = 0;
            if (row.getCell(27) != null){
                exquisiteDegree = row.getCell(27).getNumericCellValue();
            }
            //获取柔和程度
            double softDegree = 0;
            if (row.getCell(28) != null){
                softDegree = row.getCell(28).getNumericCellValue();
            }
            //获取圆润感
            double roundFeeling = 0;
            if (row.getCell(29) != null){
                roundFeeling = row.getCell(29).getNumericCellValue();
            }
            //获取刺激程度
            double stimulateDegree = 0;
            if (row.getCell(30) != null){
                stimulateDegree = row.getCell(30).getNumericCellValue();
            }
            //获取刺激部位
            String stimulatePart = "";
            if (row.getCell(31) != null){
                stimulatePart = row.getCell(31).getStringCellValue();
            }
            //获取干净程度
            double clearDegree = 0;
            if (row.getCell(32) != null){
                clearDegree = row.getCell(32).getNumericCellValue();
            }
            //获取不适类型
            String discomfortType = "";
            if (row.getCell(33) != null){
                discomfortType = row.getCell(33).getStringCellValue();
            }
            //获取不适部位
            String discomfortPart = "";
            if (row.getCell(34) != null){
                discomfortPart = row.getCell(34).getStringCellValue();
            }
            //获取干燥感
            double dryFeeling = 0;
            if (row.getCell(35) != null){
                dryFeeling = row.getCell(35).getNumericCellValue();
            }
            //获取甜度
            double sweetDegree = 0;
            if (row.getCell(36) != null){
                sweetDegree = row.getCell(36).getNumericCellValue();
            }
            //获取价类
            int priceType = 0;
            if (row.getCell(37) != null){
                priceType = (int) row.getCell(37).getNumericCellValue();
            }
            //获取功能
            String isFunction = "";
            if (row.getCell(38) != null){
                isFunction = row.getCell(38).getStringCellValue();
            }
            //获取品牌
            String brand = "";
            if (row.getCell(39) != null){
                brand = row.getCell(39).getStringCellValue();
            }
            //获取品类
            String category = "";
            if (row.getCell(40) != null){
                category = row.getCell(40).getStringCellValue();
            }
            //定义单料烟详细对象
            TobaccoDetail tobaccoDetail = new TobaccoDetail(id ,rfidValue, batch, description, rank, ganCaoFragrant,
                    qingTianFragrant, zhengTianFragrant, jiaoTianFragrant, qingFragrant,
                    muFragrant, jiaoFragrant, xinFragrant, richness, fragranceState,
                    fragranceType, fragranceDegree, concentration, energy, fluency, mianChang,
                    fragranceQuality, fragranceQuantity, penetrability, zaQiDegree, zaQiType,
                    exquisiteDegree, softDegree, roundFeeling, stimulateDegree, stimulatePart,
                    clearDegree, discomfortType, discomfortPart, dryFeeling, sweetDegree,
                    priceType, isFunction, brand, category);
            //将详细信息保存到数据库
            tobaccoDetailMapper.insert(tobaccoDetail);
        }
        //关闭资源
        excel.close();
        //将年份数据传到数据表中
        List<YearData> yearDataList = getYearData(yearList);
        for (int i = 0; i < yearDataList.size(); i++) {
            YearData yearData = yearDataList.get(i);
            QueryWrapper<YearData> wrapper1 = new QueryWrapper<YearData>();
            wrapper1.eq("year",yearData.getYear());
            Long count = yearMapper.selectCount(wrapper1);
            if (count < 1){
                //不存在的，创建条目
                yearMapper.insert(yearData);
            }else {
                yearMapper.updateNumber(yearData);
            }
        }
//        将产地信息保存到数据库
        List<LocationData> locationDataList = getLocationData(locationList);
        LocationData foreign = new LocationData();
        //将国外单料烟信息加入列表
        foreign.setLocation("国外");
        foreign.setNumber(foreignCount);
        locationDataList.add(foreign);
        for (int i = 0; i < locationDataList.size(); i++) {
            deskMapper.updateLocationData(locationDataList.get(i));
        }
        //将rfid数据上传至数据库
        deskMapper.saveRfid(rfidList);
        //将单料烟数据入库
        tobaccoMapper.uploadTobaccoBasic(basicList);
        //更新单料烟的个数
        deskMapper.updateCategories(basicList.size());

    }

    //根据rfid记录不足的单料烟信息
    @Override
    public List<TobaccoBasic> recordTobaccoShort(List<Long> rfidList) {
        //根据rfid查找单料烟
        QueryWrapper<TobaccoBasic> wrapper = new QueryWrapper<TobaccoBasic>();
        wrapper.in("rfid",rfidList);
        List<TobaccoBasic> list = tobaccoMapper.selectList(wrapper);
        log.info("不足的单料烟信息:{}",list);
        //将单料烟信息添加到不足表中
        tobaccoMapper.recordTobaccoShort(list);
        return list;
    }

    //导出不足单料烟的信息
    @Override
    @Transactional
    public void downloadShort(HttpServletResponse response) {
        //直接查询不足表中的所有单料烟信息
        List<TobaccoBasic> list = tobaccoMapper.selectShortList();
        downLoadData(response, list);
        //删除不足表中的所有信息
        tobaccoMapper.deleteAllRecordAbortShort();
    }

    //获取不足的单料烟数据
    @Override
    public List<TobaccoBasic> getTobaccoShort() {
        List<TobaccoBasic> list = tobaccoMapper.selectShortList();
        return list;
    }

    //根据rfid删除不足单料烟信息
    @Override
    public void delTobaccoShort(Long rfid) {
        tobaccoMapper.deleteShortByRfid(rfid);
    }

    //下载数据
    private void downLoadData(HttpServletResponse response, List<TobaccoBasic> list) {
        try {
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("templates/单料烟基本信息表模板.xlsx");
            if (inputStream != null) {
                XSSFWorkbook excel = new XSSFWorkbook(inputStream);
                XSSFSheet sheet = excel.getSheetAt(0);
                for (int i = 0; i < list.size(); i++) {
                    XSSFRow row = sheet.createRow(i + 1);
                    //写入数据
                    row.createCell(0).setCellValue(list.get(i).getName());
                    row.createCell(1).setCellValue(list.get(i).getLocation());
                    row.createCell(2).setCellValue(list.get(i).getYear().toString());
                    row.createCell(3).setCellValue(list.get(i).getPart());
                    if (list.get(i).getEvaluate() == 1){
                        row.createCell(4).setCellValue("已评估");
                    }else {
                        row.createCell(4).setCellValue("未评估");
                    }
                    row.createCell(5).setCellValue(list.get(i).getInfo());
                }
                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
                String fileName = URLEncoder.encode("单料烟信息表","utf-8");
                response.setHeader("Content-Disposition","attachment;filename="+fileName+".xlsx");
                ServletOutputStream outputStream = response.getOutputStream();
                excel.write(outputStream);
                outputStream.close();
                excel.close();
                inputStream.close();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    //统计年份数据
    private static List<YearData> getYearData(List<Year> yearList) {
        yearList = yearList.stream().sorted().toList();
        //统计年份数据
        int count = 1;
        List <YearData> yearDataList = new ArrayList<>();
        Year tempYear = yearList.get(0);
        for (int i = 1; i < yearList.size(); i++) {
            if (tempYear.equals(yearList.get(i))){
                count ++;
            }else {
                YearData yearData = new YearData();
                yearData.setYear(tempYear);
                yearData.setNumber(count);
                yearDataList.add(yearData);
                tempYear = yearList.get(i);
                count =1;
            }
        }
        //将最后个年份的数据添加到列表中
        YearData yearData = new YearData();
        yearData.setYear(tempYear);
        yearData.setNumber(count);
        yearDataList.add(yearData);
        return yearDataList;
    }

    //统计中国产地数据
    private List<LocationData> getLocationData(List<String> locationList) {
        locationList = locationList.stream().sorted().collect(Collectors.toList());
        List<LocationData> locationDataList = new ArrayList<>();
        String location = locationList.get(0);
        int count = 1;
        for (int i = 1; i < locationList.size(); i++) {
            if (locationList.get(i).equals(location)){
                count++;
            }else {
                LocationData locationData = new LocationData();
                locationData.setNumber(count);
                locationData.setLocation(location);
                locationDataList.add(locationData);
                location = locationList.get(i);
                count = 1;
            }
        }
        //将列表最后一个产地数据添加到列表
        LocationData locationData = new LocationData();
        locationData.setLocation(location);
        locationData.setNumber(count);
        locationDataList.add(locationData);
        return locationDataList;
    }

    //判断单料烟的产地是不是在中国
    private boolean isChineseTobacco(String location){
        for (String str : province) {
            if (location.contains(str)){
                return true;
            }
        }
        return false;
    }

}
